//     av-adapter.js 1.5.1
//     http://www.atjava.com
//     (c) 2015 Kyo Jin, ATJAVA.COM Inc.

"use strict";

function isBlank(obj){
	return obj == undefined || obj == null || obj == "";
}

function randomString(len) {
	len = len || 32;
	var $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
	var maxPos = $chars.length;
	var str = '';
	for (var i = 0; i < len; i++) {
		str += $chars.charAt(Math.floor(Math.random() * maxPos));
	}
	return str;
}

function arrayClone(src){
	var target = new Array();
	for (var i = 0; i < src.length; i++) {
		target.push(src[i]);
	}
	return target;
}

function compileAndRender(template,data){
	if(isBlank(template))
		return "";
	var _compiledTmpl = Template7.compile(template);
	return _compiledTmpl(data);
}

function SailsAdapter(app,config) {
	
	var _this = this;
	
	this._init = function(){
		
		
		
	};
	
	this.showErrorMessage = function(message){
		app.alert(message,"错误");
	};
	this.showWarningMessage = function(message){
		app.alert(message,"警告");
	};
	this.showInfoMessage = function(message){
		app.alert(message,"信息");
	};
	
	this._defaultSuccessHandler = function(element,object){
		var _success = element.attr("success");
		if(_success){
			var _successFunc = eval(_success);
			_successFunc(object);
		}
		
	};
	
	this._defaultErrorHandler = function(element, error){
		var _error = element.attr("error");
		if(_error){
			var _errorFunc = eval(_error);
			_errorFunc(error);
		}
		this._hidePreloader();
		this.showErrorMessage(error.message);
		
	};
	
	this.getConvertedValue = function(_dataType,_elementValue){
		
		var _newVal = compileAndRender(_elementValue, {});
		
		if(_dataType == "Number"){
			_newVal = Number(_newVal);
		}else if(_dataType == "Date"){
			_newVal = new Date(Date.parse(_newVal));
		}else{
			
		}
		return _newVal;
		
	};
	
	this.configDelete = function(link,page){
		
		link.on("click",function(){
			
			//Custom message
			var _confirmMessage = link.attr("message");
			_confirmMessage = isBlank(_confirmMessage) ? "确定要删除吗?" : _confirmMessage;
			
			var _deleteErrorHandler = function(error){
				_this._defaultErrorHandler(link, error);
			};
			
			//Confirm
			app.confirm(_confirmMessage, "警告" ,function () {
				
				_this._showPreloader();
				
				var _Entity = _this.entities[link.attr("entity")];
				var _pkey = link.attr("pk");
				
				//Delete Object
				_this._deleteObject(_Entity, _pkey, link)
				.then(function(object){
					
					//Delete Cascade Pointer
					return _this._deleteCascadePointer(object,link);
					
				},_deleteErrorHandler)
				
				.then(function(object){
					
					//Delete Cascade Entity
					_this._deleteCascadeEntity(object,link);
					
				},_deleteErrorHandler)
				
				.then(function(object){
					
					//Success
					_this._defaultSuccessHandler(link, object);
					_this._hidePreloader();
					_this.renderPage(page);
					
				},_deleteErrorHandler);
				
				
			});
		});
	};
	
	this._deleteObject = function(_type,_pkey,element){
		
		var _query = new AV.Query(_type);
		
		//Get entity Object
		return _query.get(_pkey).then(function(object) {
			
			//Destroy
			return object.destroy();
			
		});
	};
	
	this._deleteObjectByPointer = function(_type,_prop,_pointer,element){
		
		var _query = new AV.Query(_type);
		
		_query.equalTo(_prop, _pointer);
		
		return _query.destroyAll();
	};
	
	this._deleteCascadeEntity = function(object,element){
		
		var _cascadeEntity = element.attr("cascade-entity");
		
		if(isBlank(_cascadeEntity)){
			return new AV.Promise(function(resolve, reject){
				resolve(object);
			});
		}
		
		var _cascadeProp = element.attr("cascade-prop");
		var _CascadeEntityType = _this.entities[_cascadeEntity];
		
		//Delete Cascade Entity
		return _this._deleteObjectByPointer(_CascadeEntityType ,_cascadeProp, object, element);
		
	};
	
	this._deleteCascadePointer = function(object,element){
		
		var _cascadePointer = element.attr("cascade-pointer");
		
		if(isBlank(_cascadePointer)){
			return new AV.Promise(function(resolve, reject){
				resolve(object);
			});
		}
		
		var _cascadeType = _this.entities[object.get(_cascadePointer).className];
		var _cascadeId = object.get(_cascadePointer).id;
		
		//Delete Cascade Pointer
		return _this._deleteObject(_cascadeType ,_cascadeId, element);
	};
	
	this.setPointers = function(container, _instance){
		
		//Entity pointers
		$.each(container.find("*[ptype]"), function(){
			
			var _pointerName = $(this).attr("name");
			var _option = $(this).attr("option");
			var _PointerType = _this.entities[$(this).attr("ptype")];
			
			var _pointer = null;
			
			//create
			if(_option == "create"){
				
				_pointer = new _PointerType();
				
			//update
			}else if(_option == "update"){
				
				_pointer = _instance.get(_pointerName);
				
			}
			
			if(_pointer != null){
				$.each(container.find("*[pointer='"+_pointerName+"'][pname]"), function(){
					
					var _propName = $(this).attr("pname");
					_this.setInstanceProp($(this), _pointer, _propName, $(this).val());
					
				});
				_instance.set(_pointerName,_pointer);
			}
		});
	};
	
	this.setInstanceProp = function(element, _instance, _elementName, _elementValue){
		
		var _dataType = element.attr("dtype");
		_dataType = isBlank(_dataType) ? "String" : _dataType;
		
		if(isBlank(_elementName)){
			return ;
		}
		
		if(this.entities[_dataType] != undefined){
			var _PointerType = this.entities[_dataType];
			var _pointer = new _PointerType();
			_pointer.id = _this.getConvertedValue("String",_elementValue);
			_instance.set(_elementName,_pointer);
		}else{
			_instance.set(_elementName,this.getConvertedValue(_dataType,_elementValue));
		};
	};
	
	this.form2Instance = function(form,_instance){
		
		//Entity properties
		$.each(form.find("*[name]"), function(){
			
			if($(this).is("*[ptype]")){
				return ;
			}
			
			var _elementType = $(this).attr("type");
			var _elementName = $(this).attr("name");
			var _elementValue = "";
			
			if(_elementType == "radio" && _instance.get(_elementName) != undefined)
				return ;
			
			if(_elementType == "radio"){
				_elementValue = form.find("input[type='radio'][name='"+_elementName+"']:checked").val();
			}else{
				_elementValue = $(this).val();
			}
			
			_this.setInstanceProp($(this), _instance, _elementName, _elementValue);
			
		});
	};
	
	this.processSaveUpdate = function(form, _instance, _operator){
		
		var _saveUpdateHandler = {
				success : function(object) {
					_this._defaultSuccessHandler(form, object);
					_this._hidePreloader();
				},
				error : function(object, error) {
					_this._defaultErrorHandler(form, error);
					_this._hidePreloader();
				}
			};
		
		var _beforeSave = form.attr("before-save");
		var _customSave = form.attr("custom-save");
		
		_this.form2Instance(form,_instance);
		
		//Configuration Pointers
		_this.setPointers(form, _instance);
		
		if(!isBlank(_beforeSave)){
			var _beforeSaveFunc = eval(_beforeSave);
			_beforeSaveFunc(_operator, _instance);
		}

		if(!isBlank(_customSave)){
			var _customSaveFunc = eval(_customSave);
			_customSaveFunc(_instance, _saveUpdateHandler);
		}else{
			//Default Save
			_instance.save(null,_saveUpdateHandler);
		}
		
	};
	
	this.configSaveUpdate = function(form,page){
		
		form.validate({
			showErrors : function(errorMap, errorList) {
				if(errorList.length == 0)
					return;
				var popoverHTML = 
					'<div class="popover" style="min-width:160px;width:auto;"><div class="popover-inner">'+
					'<div class="content-block" style="margin:15px 0">'+ errorList[0].message + '</div>'+
					'</div></div>';
				
				app.popover(popoverHTML, errorList[0].element);
			}
		});
		
		var _Entity = _this.entities[form.attr("entity")];
		
		form.find("a[option='update']").on("click",function(){
			
			var _operator = this;
			
			//Validate
			if(!form.valid()){
				return;
			}
			
			_this._showPreloader();
			
			//Load instance data
			var query = new AV.Query(_Entity);
			var _pk = form.attr("pk");
			_pk = compileAndRender(_pk,{});
			
			//Pointer
			var _includes = form.attr("include");
			if(!isBlank(_includes)){
				$.each(_includes.split(","),function(){
					query.include(this);
				});
			}
			
			query.get(_pk).then(function(object) {
				
				var _instance = object;
				_this.processSaveUpdate(form, _instance, _operator);
				
			},function(error){
				_this._defaultErrorHandler(element, error);
			});
			
		});
		
		form.find("a[option='save']").on("click",function(){
			
			var _operator = this;
			
			//Validate
			if(!form.valid()){
				return;
			}
			
			_this._showPreloader();
			
			var _instance = new _Entity();
			_this.processSaveUpdate(form, _instance, _operator);
			
		});
		
	};
	
	this._showPreloader = function(){
		app.showPreloader();
	};
	
	this._hidePreloader = function(){
		app.hidePreloader();
	};
	
	this.configPageOption = function(page){
		
		$("a[entity]",page).each(function(){
			_this.configDelete($(this),page);
		});
		
		$("form[entity]",page).each(function(){
			_this.configSaveUpdate($(this),page);
		});
		
		//Setup Number keypad
		$("input[type='text'][dtype='Number']",page).each(function(){
			_this._setupKeypad(this);
		});
		
	};
	
	this._setupKeypad = function(input){
		var maxLen = $(input).attr("maxlength");
		app.keypad({
			input: input,
			toolbarCloseText : '完成',
			valueMaxLength : maxLen
		});
	};
	
	this._init();
	
};
